package cn.com.pc.content.controller;

import cn.com.pc.content.annotation.LogRequired;
import cn.com.pc.content.domain.Biz;
import cn.com.pc.content.domain.Site;
import cn.com.pc.content.domain.tag.Tag;
import cn.com.pc.content.domain.tag.TagTree;
import cn.com.pc.content.domain.tag.TagTreeNotFoundException;
import cn.com.pc.content.dto.*;
import cn.com.pc.content.service.TagService;
import cn.com.pc.content.service.TagTreeService;
import cn.com.pc.content.util.BeanUtils;
import cn.com.pc.content.util.JsonUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * 标签导航树管理
 *
 */
@RestController
@RequestMapping("/tag-trees")
@Slf4j
public class TagTreeController {

    @Autowired
    private TagTreeService tagTreeService;

    @Autowired
    private TagService tagService;

    @Autowired
    private HttpServletRequest request;

    /**
     * 新增标签导航树
     * @param site
     * @param biz
     * @param tagTreeDTO
     * @return
     */
    @PostMapping
    @LogRequired(operation = "'新增标签树' + #_return")
    public Long createTagTree(@RequestAttribute("site") Site site, @RequestAttribute("biz") Biz biz, @Validated @RequestBody TagTreeDTO tagTreeDTO) {
        // 判空
        Long parentId = tagTreeDTO.getParentId();
        if (parentId != null && parentId != 0) {
            TagTree tagTree = tagTreeService.getTagTreeById(parentId);
            if (tagTree == null || tagTree.getSite() != site) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "父标签树不存在");
            }
        }
        // 查重
        if (tagTreeService.existsTagTreeByName(site, biz, tagTreeDTO.getName())) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "标签树名称已存在");
        }

        tagTreeDTO.setSite(site);
        tagTreeDTO.setBiz(biz);
        tagTreeDTO.setCreatedAt(LocalDateTime.now());
        tagTreeDTO.setUpdatedAt(LocalDateTime.now());
        return tagTreeService.createTagTree(tagTreeDTO);
    }


    /**
     * 查询标签导航树列表
     * @param site
     * @param biz
     * @param tagTreeDTO
     * @return
     */
    @GetMapping
    public PageResult<TagTree> listTagTreesByDTO(@RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, TagTreeDTO tagTreeDTO, PageForm pageForm, Sort sort) {
        tagTreeDTO.setSite(site);
        tagTreeDTO.setBiz(biz);
        return tagTreeService.listTagTreesByDTO(tagTreeDTO, pageForm, sort);
    }


    /**
     * 查询标签导航树详情
     * @param site
     * @param tagTreeId
     * @return
     */
    @GetMapping("/{tagTreeId:\\d+}")
    public ObjectNode getTagTreeById(@RequestAttribute("site") Site site, @PathVariable Long tagTreeId, TagRelationDTO tagRelationDTO, PageForm pageForm) {
        TagTree tagTree = tagTreeService.getTagTreeById(tagTreeId);
        if (tagTree == null || tagTree.getSite() != site) {
            throw new TagTreeNotFoundException();
        }
        // 查询导航树节点下的标签
        PageResult<Tag> tags = tagService.listTagsByTreeIdAndTagRelationDTO(tagTreeId, tagRelationDTO, pageForm);

        ObjectNode result = (ObjectNode) JsonUtils.obj2JsonNode(tagTree);
        JsonNode tagsNode = JsonUtils.obj2JsonNode(tags);
        if (result != null) {
            result.set("tags", tagsNode);
        }
        return result;
    }


    /**
     * 修改标签导航树
     * @param site
     * @param tagTreeId
     * @return
     */
    @PutMapping("/{tagTreeId:\\d+}")
    @LogRequired(operation = "'修改标签树' + #tagTreeId")
    public TagTree updateTagTreeByDTO(@RequestAttribute("site") Site site, @RequestAttribute("biz") Biz biz, @PathVariable Long tagTreeId, @Validated @RequestBody TagTreeDTO tagTreeDTO) {
        // 判空
        TagTree tagTree = tagTreeService.getTagTreeById(tagTreeId);
        if (tagTree == null || tagTree.getSite() != site) {
            throw new TagTreeNotFoundException();
        }
        Long parentId = tagTreeDTO.getParentId();
        if (parentId != null && parentId != 0) {
            TagTree tagParent = tagTreeService.getTagTreeById(parentId);
            if (tagParent == null || tagParent.getSite() != site) {
                throw new TagTreeNotFoundException();
            }
        }

        // 查重
        if (!tagTreeDTO.getName().equals(tagTree.getName())) {
            if (tagTreeService.existsTagTreeByName(site, biz, tagTreeDTO.getName())) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "标签树名称已存在");
            }
        }

        tagTreeDTO.setSite(site);
        tagTreeDTO.setBiz(biz);
        tagTreeDTO.setUpdatedAt(LocalDateTime.now());
        try {
            request.setAttribute("operation", "，修改属性" + BeanUtils.comparePropertyIgnore(tagTree, tagTreeDTO, "id", "createdAt", "updatedAt", "subTree"));
        } catch (Exception e) {
            log.warn("标签树{}生成修改日志有误", tagTreeId);
            e.printStackTrace();
        }
        return tagTreeService.updateTagTreeByDTO(tagTreeDTO, tagTree);
    }


    /**
     * 删除标签树
     * @param site
     * @param tagTreeId
     */
    @DeleteMapping("/{tagTreeId:\\d+}")
    @LogRequired(operation = "'删除标签树' + #tagTreeId")
    public void deleteTagTree(@RequestAttribute("site") Site site,  @PathVariable Long tagTreeId, @RequestBody boolean force) {
        // 判空
        TagTree tagTree = tagTreeService.getTagTreeById(tagTreeId);
        if (tagTree == null || tagTree.getSite() != site) {
            throw new TagTreeNotFoundException();
        }
        // 必须为末端标签树
        if (tagTree.getSubTree().size() > 0) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "标签树存在子集");
        }
        // 已关联标签
        if (tagService.existsTagByTreeId(tagTreeId) && !force) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "标签树存在关联标签");
        }
        tagTreeService.deleteTagTree(tagTreeId);
    }

}
